package stackoverflow.domain.question;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.HashCodeBuilder;

import stackoverflow.domain.user.User;

public class Question extends Post  
{
	private Set<Tag> tags;
	private List<Answer> answers;

	public static class QuestionBuilder
	{
		private Post post= new Post();
		private Set<Tag> tags;

		private static final String userMustNotBeNull="User must not be null";
		private static final String textMustNotBeNull="Text must not be null";		
		private static final String tagsMustNotBeNull="Tags must not be null";				
		private static final String atLeastOneTagRequired ="Question requires at least one tag.";
		private static final String textRequired = "Question must have some text.";
		private static final String tagNotFound="Question does not contain the specified tag.";
		
		public QuestionBuilder(User postedByUser)
		{
			this.post.postedBy = postedByUser;
		}
		
		public QuestionBuilder postText(String postText)
		{ 
			this.post.text = postText; 
			return this; 
		}

		public QuestionBuilder addTags(Set<Tag> tags)
        { 
			this.tags = tags; 
			return this; 
		}
		
		public Question build() 
		{
			Validate.notNull(this.post.postedBy, userMustNotBeNull);
			Validate.notNull(this.post.text, textMustNotBeNull);
			Validate.notNull(this.tags, tagsMustNotBeNull);
			Validate.notEmpty(this.tags, atLeastOneTagRequired);
			Validate.notEmpty(this.post.text, textRequired);
			return new Question(this);
	    }
	}
	
	private Question(QuestionBuilder questionBuilder) 
	{
		this.postedBy = questionBuilder.post.postedBy;
		this.text = questionBuilder.post.text;

		this.tags = questionBuilder.tags;
		this.answers= new ArrayList<Answer>();
	}
	
	public Set<Tag> getTags()
	{
		return Collections.unmodifiableSet(tags);
	}

	public void addTag(Tag tag) 
	{
		if(!tags.contains(tag))
		{
			tags.add(tag);
		}
	}

	public void removeTag(Tag tag) throws TagNotFoundException
	{	
		Validate.notEmpty(tags, QuestionBuilder.atLeastOneTagRequired);
		if(!tags.contains(tag))
		{
			throw new TagNotFoundException(QuestionBuilder.tagNotFound);
		}
		tags.remove(tag);
	}
	
	public List<Answer> getAnswers()
	{
		return Collections.unmodifiableList(answers);
	}
	
	public void postAnswer(Answer answer)
	{
		this.answers.add(answer);
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(id).toHashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		Question other = (Question) obj;
		return id.equals(id);
	}
}
